/**
 * @file eigen_share.h
 *
 * Shared arrays/matrics
 *
 * @author Dahua Lin
 */

#ifdef _MSC_VER
#pragma once
#endif

#ifndef SLIPP_EIGEN_SHARE_H_
#define SLIPP_EIGEN_SHARE_H_

#include <slipp/base/basic_defs.h>
#include <Eigen/Dense>
#include <memory>

namespace sli
{

	template<class Internal>
	class eigen_share_base
	{
	public:
		typedef Internal internal_type;
		typedef typename internal_type::Scalar Scalar;
		enum
		{
			RowsAtCompileTime = internal_type::RowsAtCompileTime,
			ColsAtCompileTime = internal_type::ColsAtCompileTime
		};

	protected:
		eigen_share_base(internal_type *p)
		: m_p_internal(p)
		{
		}

	public:
		internal_type& get()
		{
			return *m_p_internal;
		}

		const internal_type& get() const
		{
			return *m_p_internal;
		}

		index_t rows() const
		{
			return m_p_internal->rows();
		}

		index_t cols() const
		{
			return m_p_internal->cols();
		}

		index_t size() const
		{
			return m_p_internal->size();
		}

		Scalar* data()
		{
			return m_p_internal->data();
		}

		const Scalar* data() const
		{
			return m_p_internal->data();
		}

	private:
		std::shared_ptr<internal_type> m_p_internal;

	}; // end class eigen_share_base


	template<typename ScalarType, int Rows=Eigen::Dynamic, int Cols=Eigen::Dynamic>
	class eigen_share_array : public eigen_share_base<Eigen::Array<ScalarType, Rows, Cols> >
	{
	public:
		typedef eigen_share_base<Eigen::Array<ScalarType, Rows, Cols> > base;
		typedef typename base::internal_type internal_type;

		eigen_share_array()
		: base(new internal_type())
		{
		}

		eigen_share_array(index_t n)
		: base(new internal_type(n))
		{
		}

		eigen_share_array(index_t m, index_t n)
		: base(new internal_type(m, n))
		{
		}

		eigen_share_array(const internal_type& a)
		: base(new internal_type(a))
		{
		}

	}; // end class eigen_share_array


	template<typename ScalarType, int Rows=Eigen::Dynamic, int Cols=Eigen::Dynamic>
	class eigen_share_matrix : public eigen_share_base<Eigen::Matrix<ScalarType, Rows, Cols> >
	{
	public:
		typedef eigen_share_base<Eigen::Matrix<ScalarType, Rows, Cols> > base;
		typedef typename base::internal_type internal_type;

		eigen_share_matrix()
		: base(new internal_type())
		{
		}

		eigen_share_matrix(index_t n)
		: base(new internal_type(n))
		{
		}

		eigen_share_matrix(index_t m, index_t n)
		: base(new internal_type(m, n))
		{
		}

		eigen_share_matrix(const internal_type& a)
		: base(new internal_type(a))
		{
		}

	}; // end class share_array
}

// typedefs



namespace sli
{

}

#endif


